package com.david.http.http.util

import android.util.Log
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.LifecycleOwner
import androidx.lifecycle.lifecycleScope
import androidx.lifecycle.repeatOnLifecycle
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.async
import kotlinx.coroutines.coroutineScope
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.catch
import kotlinx.coroutines.flow.collectLatest
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.flow
import kotlinx.coroutines.flow.flowOn
import kotlinx.coroutines.flow.lastOrNull
import kotlinx.coroutines.flow.onCompletion
import kotlinx.coroutines.flow.onStart
import kotlinx.coroutines.flow.zip
import kotlinx.coroutines.launch

//参考链接：https://juejin.cn/post/7034381227025465375
fun <T> Flow<T>.request(
    lifecycleOwner: LifecycleOwner,
    isOnlyResume: Boolean = true,
    block: (T) -> Unit
) {
    lifecycleOwner.lifecycleScope.apply {
        if (isOnlyResume) {
            launch {
                lifecycleOwner.repeatOnLifecycle(Lifecycle.State.RESUMED) {
                    this@request.onStart {
                        Log.e("error", "request onStart")
                    }.catch {
                        Log.e("error", "request error: ${it.message}")
                    }.onCompletion {
                        Log.e("error", "request onCompletion error: ${it?.message}")
                    }.collectLatest {
                        block(it)
                    }
                }
            }
        } else {
            launch {
                this@request.onStart {
                    Log.e("error", "request onStart")
                }.catch {
                    Log.e("error", "request error: ${it.message}")
                }.onCompletion {
                    Log.e("error", "request onCompletion error: ${it?.message}")
                }.collectLatest {
                    block(it)
                }
            }
        }
    }
}

/**
 * 直接返回Pair结果的zip，对于简单的结果接收可用（不用对数据混合处理时），如需对结果处理则使用系统提供的zip在transform中处理即可
 *
 * 使用combine：
 * fun <T1, T2> Flow<T1>.ziptwo(flow2: Flow<T2>): Flow<Pair<T1?, T2?>> {
 *     return this.combine(flow2) { one, two ->
 *         Pair(one, two)
 *     }
 * }
 */
fun <T1, T2> Flow<T1>.zipResultPair(flow2: Flow<T2>): Flow<Pair<T1, T2>> {
    return this.zip(flow2) { one, two ->
        Pair(one, two)
    }
}

/**
 * 组合三个flow并返回Triple携带三个结果，不对结果处理直接使用Triple返回，如需对结果处理使用系统提供的combine即可；更多个flow使用系统combine即可
 */
fun <T1, T2, T3> Flow<T1>.combineResultTriple(flow2: Flow<T2>,
    flow3: Flow<T3>): Flow<Triple<T1?, T2?, T3?>> {
    return combine(this, flow2, flow3) { one, two, three ->
        Triple(one, two, three)
    }
}

/**
 * zip4直接使用公共方法：[kotlinx.coroutines.flow.combine]，示例：
val flow1 = listOf(1, 2, 3).asFlow()
val flow2 = listOf(1, 2, 3).asFlow()
val flow3 = listOf(1, 2, 3).asFlow()
val flow4 = listOf(1, 2, 3).asFlow()
val flow5 = listOf(1, 2, 3).asFlow()
val flow6 = listOf(1, 2, 3).asFlow()
val flow7 = listOf(1, 2, 3).asFlow()

combine(flow1, flow2, flow3, flow4, flow5) { one, two, three, four ,five ->
arrayOf(one, two, three, four, five)
}.collectLatest {

}
//超过5个则会调用变长变量方法
combine(flow1, flow2, flow3, flow4, flow5, flow6) { items ->
items
}.collectLatest {

}
 */